import sys
import os

from LMG.Utility.configreader import ConfigReader
from LMG.Utility.constants import * # pylint: disable-msg = W0611,W0401

"""
Handles torrent config
TODO:
 - tracker list
"""

################################################################

class TorrentConfig(ConfigReader):
    """
    Handles reading and writing information about this torrent
    to the torrent.list file.
    """
    def __init__(self, torrent):
        self.torrent = torrent
        
        basepath = os.path.join(utility.getConfigPath(), "torrentinfo")

        filename = self.torrent.infohash + ".info"
        configpath = os.path.join(basepath, filename)
        ConfigReader.__init__(self, configpath, "TorrentInfo")

        self.writeflags = { WRITEFLAG_SRC: False, 
                            WRITEFLAG_BASICINFO: False, 
                            WRITEFLAG_STATUS: False, 
                            WRITEFLAG_PRIO: False, 
                            WRITEFLAG_FILEPRIO: False, 
                            WRITEFLAG_FILEPROGRESS: False,
                            WRITEFLAG_PROGRESS: False, 
                            WRITEFLAG_UPLOADPARAMS: False, 
                            WRITEFLAG_NAMEPARAMS: False, 
                            WRITEFLAG_SEEDTIME: False }
    
    def writeAll(self):
        """
        Write out all config values for the torrent
        """    
        overallchange = False
        
        if self.writeSrc(False):
            overallchange = True
        if self.writeBasicInfo(False):
            overallchange = True
        if self.writeStatus(False):
            overallchange = True
        if self.writePriority(False):
            overallchange = True
        if self.writeFilePriorities(False):
            overallchange = True
        if self.writeProgress(False):
            overallchange = True
        if self.writeUploadParams(False):
            overallchange = True
        if self.writeNameParams(False):
            overallchange = True
        if self.writeSeedTime(False):
            overallchange = True
        if self.writeFileProgress(False):
            overallchange = True

        if overallchange:
            self.Flush()
        
    def writeSrc(self, flush = True):
        """
        Write out information on the source file for the torrentthe
        """
        if self.writeflags[WRITEFLAG_SRC]:
            return
        self.writeflags[WRITEFLAG_SRC] = True
                
        torrent = self.torrent
        overallchange = False

        # Write torrent information
        if torrent.HasMetadata():
            filename = os.path.split(torrent.src)[1]
        else:
            filename = torrent.getMagnetLink()
        index = str(self.torrent.listindex)
        if utility.torrentconfig.Write(index, "\"" + filename + "\""):
            overallchange = True
        
        if overallchange and flush:
            utility.torrentconfig.Flush()
        
        self.writeflags[WRITEFLAG_SRC] = False
        return overallchange
        
    def writeBasicInfo(self, flush = True):
        """
        Write out basic information about the torrent
        """
        if self.writeflags[WRITEFLAG_BASICINFO]:
            return
        self.writeflags[WRITEFLAG_BASICINFO] = True
        
        torrent = self.torrent
        
        overallchange = False
        
        if self.Write("dest", torrent.files.dest):
            overallchange = True

        if self.Write("label", torrent.files.activelabel):
            overallchange = True

        if self.Write("addedtime", int(torrent.addedTime)):
            overallchange = True

        if self.Write("completedtime", int(torrent.completedTime)):
            overallchange = True

        if overallchange and flush:
            self.Flush()
        
        self.writeflags[WRITEFLAG_BASICINFO] = False
        return overallchange
    
    def writeNameParams(self, flush = True):
        """
        Write out the torrent's name
        """
        if self.writeflags[WRITEFLAG_NAMEPARAMS]:
            return
        self.writeflags[WRITEFLAG_NAMEPARAMS] = True
        
        torrent = self.torrent
        overallchange = False
        
        # Write settings for name if available
        title = torrent.title
        if title is not None:
            if title == "":
                title = " "
            if self.Write("title", title):
                overallchange = True
        else:
            if self.DeleteEntry("title"):
                overallchange = True

        if overallchange and flush:
            self.Flush()
            
        self.writeflags[WRITEFLAG_NAMEPARAMS] = False
        return overallchange

    def writeUploadParams(self, flush = True):
        """
        Write out the torrent's upload settings
        """ 
        if self.writeflags[WRITEFLAG_UPLOADPARAMS]:
            return
        self.writeflags[WRITEFLAG_UPLOADPARAMS] = True
        
        torrent = self.torrent
        
        overallchange = False
        
        # Write settings for local upload rate if available
        localmax = torrent.connection.getLocalRate("up")
        if localmax != 0:
            if self.Write("localmax", localmax):
                overallchange = True
        else:
            if self.DeleteEntry("localmax"):
                overallchange = True

        localmaxdown = torrent.connection.getLocalRate("down")
        if localmaxdown != 0:
            if self.Write("localmaxdown", localmaxdown):
                overallchange = True
        else:
            if self.DeleteEntry("localmaxdown"):
                overallchange = True

        maxupload = torrent.connection.getMaxUpload(localonly = True)
        if maxupload is not None:
            if self.Write("maxupload", maxupload):
                overallchange = True
        else:
            if self.DeleteEntry("maxupload"):
                overallchange = True

        if self.Write("announces", torrent.trackerlist, "bencode-list"):
            overallchange = True
        #announces = torrent.trackerlist
        #if announces:
        #    if self.Write("announces", announces, "bencode-list"):
        #        overallchange = True
        #else:
        #    if self.DeleteEntry("announces"):
        #        overallchange = True

        for param in torrent.connection.seedoptions:
            value = torrent.connection.getSeedOption(param, localonly = True)
            if value is not None:
                if self.Write(param, value):
                    overallchange = True
            else:
                if self.DeleteEntry(param):
                    overallchange = True
                
        if not torrent.connection.timeout:
            if self.Write("timeout", "0"):
                overallchange = True
        else:
            if self.DeleteEntry("timeout"):
                overallchange = True

        if overallchange and flush:
            self.Flush()
            
        self.writeflags[WRITEFLAG_UPLOADPARAMS] = False
        return overallchange
            
    def writeProgress(self, flush = True):
        """
        Write out the torrent's progress
        """
        if self.writeflags[WRITEFLAG_PROGRESS]:
            return
        self.writeflags[WRITEFLAG_PROGRESS] = True
            
        torrent = self.torrent
        overallchange = False
        
        if self.Write("downsize", ('%.0f' % torrent.files.downsize)):
            overallchange = True
        if self.Write("upsize", ('%.0f' % torrent.files.upsize)):
            overallchange = True
        if self.Write("sizedone", ('%.1f' % torrent.files.sizeDone)):
            overallchange = True
        if self.Write("progress", ('%.1f' % torrent.files.progress)):
            overallchange = True
        
        if overallchange and flush:
            self.Flush()
        
        self.writeflags[WRITEFLAG_PROGRESS] = False
        return overallchange
        
    def writeStatus(self, flush = True):
        """
        Write out the torrent's status
        """ 
        if self.writeflags[WRITEFLAG_STATUS]:
            return
        self.writeflags[WRITEFLAG_STATUS] = True

        torrent = self.torrent
        overallchange = False
               
        value = torrent.status.value
        oldvalue = torrent.actions.oldstatus
        if oldvalue is None:
            oldvalue = 0

        if (value == STATUS_FINISHED
            or (value == STATUS_HASHCHECK and oldvalue == STATUS_FINISHED)):
            status = 2    # Torrent is finished
        elif value == STATUS_STOP:
            status = 1    # Torrent is stopped
        else:
            status = 0    # Torrent is queued
        
        if status != 0:
            if self.Write("statusvalue", status):
                overallchange = True
        else:
            if self.DeleteEntry("statusvalue"):
                overallchange = True
            
        if torrent.status.completed:
            if self.Write("complete", "1"):
                overallchange = True
        else:
            if self.DeleteEntry("complete"):
                overallchange = True

        if overallchange and flush:
            self.Flush()
        
        self.writeflags[WRITEFLAG_STATUS] = False
        return overallchange
        
    def writePriority(self, flush = True):
        """
        Write out the torrent's priority
        """
        if self.writeflags[WRITEFLAG_PRIO]:
            return
        self.writeflags[WRITEFLAG_PRIO] = True
            
        torrent = self.torrent
        overallchange = False
        
        if self.Write("prio", torrent.prio):
            overallchange = True

        if overallchange and flush:
            self.Flush()
            
        self.writeflags[WRITEFLAG_PRIO] = False
        return overallchange
        
    def writeSeedTime(self, flush = True):
        """
        Write out how long the torreent has been seeding for
        """
        if self.writeflags[WRITEFLAG_SEEDTIME]:
            return
        self.writeflags[WRITEFLAG_SEEDTIME] = True
        
        torrent = self.torrent
        overallchange = False
        
        if torrent.connection.seedingtime > 0:
            if self.Write("seedtime", int(torrent.connection.seedingtime)):
                overallchange = True
        else:
            if self.DeleteEntry("seedtime"):
                overallchange = True

        if overallchange and flush:
            self.Flush()
            
        self.writeflags[WRITEFLAG_SEEDTIME] = False
        return overallchange
        
    def writeFilePriorities(self, flush = True):
        """
        Write out the priorities for files within the torrent
        """
        if self.writeflags[WRITEFLAG_FILEPRIO]:
            return
        self.writeflags[WRITEFLAG_FILEPRIO] = True
        
        torrent = self.torrent
        overallchange = False
        
        if not self.torrent.files.isFile():
            notdefault, text = torrent.files.getFilePrioritiesAsString()
            if notdefault:
                if self.Write("fileprio", text):
                    overallchange = True
            else:
                if self.DeleteEntry("fileprio"):
                    overallchange = True
        else:
            if self.DeleteEntry("fileprio"):
                overallchange = True
            
        if overallchange and flush:
            self.Flush()
            
        self.writeflags[WRITEFLAG_FILEPRIO] = False
        return overallchange
        
    def writeFileProgress(self, flush = True):
        """
        Write out the progress for individual files within a torrent
        """
        if self.writeflags[WRITEFLAG_FILEPROGRESS]:
            return
        self.writeflags[WRITEFLAG_FILEPROGRESS] = True
                
        torrent = self.torrent
        
        overallchange = False
        
        if not torrent.files.isFile():
            if self.Write("fileprogress", torrent.files.fileprogress, "bencode-list"):
                overallchange = True
        else:
            if self.DeleteEntry("fileprogress"):
                overallchange = True
            
        if overallchange and flush:
            self.Flush()
            
        self.writeflags[WRITEFLAG_FILEPROGRESS] = False
        return overallchange
            
    def readAll(self):
        """
        Read a torrent's config information
        """
        torrent = self.torrent
        
        # Download size
        downsize = self.Read("downsize")
        if downsize != "":
            try:
                torrent.files.downsize = float(downsize)
            except:
                pass
        
        # Upload size
        upsize = self.Read("upsize")
        if upsize != "":
            try:
                torrent.files.upsize = float(upsize)
            except:
                pass
        # Done size
        sizedone = self.Read("sizedone")
        if sizedone != "":
            try:
                torrent.files.sizeDone = float(sizedone)
            except:
                pass
            
        # Status
        # Format from earlier 2.7.0 builds:
        status = self.Read("status")
        if status == "completed":
            torrent.status.completed = True
        elif status == "pause":
            torrent.status.value = STATUS_STOP

        status = self.Read("statusvalue")
        if status == "2":
            torrent.status.value = STATUS_FINISHED
        elif status == "1":
            torrent.status.value = STATUS_STOP
            
        complete = self.Read("complete", "boolean")
        if complete:
            torrent.status.completed = True
       
        # Priority
        prio = self.Read("prio")
        if prio != "":
            try:
                torrent.prio = int(prio)
            except:
                pass

        # File priorities
        fileprio = str(self.Read("fileprio"))
        if fileprio != "":
            filepriorities = fileprio.split(",")
            
            # Just in case there's a mismatch in sizes,
            # don't try to get more values than exist
            # in the source or destination arrays
            len1 = len(filepriorities)
            len2 = len(torrent.files.filepriorities)
            rangeEnd = min(len1, len2)
            for i in range(rangeEnd):
                try:
                    torrent.files.filepriorities[i] = int(filepriorities[i])
                except:
                    pass

        # File progress
        fileprogress = self.Read("fileprogress", "bencode-list")
        if fileprogress:
            for i in range(len(fileprogress)):
                try:
                    progress = int(fileprogress[i])
                except:
                    progress = -1
                fileprogress[i] = progress
            self.torrent.files.fileprogress = fileprogress

        #name
        title = self.Read("title")
        if title != "":
            torrent.title = title

        # Label
        label = self.Read("label")
        if label != "":
            torrent.files.activelabel = label

        # Added On
        addedTime = self.Read("addedtime", "int")
        if addedTime != 0:
            torrent.addedTime = addedTime

        # Completed On
        completedTime = self.Read("completedtime", "int")
        if completedTime != 0:
            torrent.completedTime = completedTime

        # Progress
        if torrent.status.completed or torrent.status.value == STATUS_FINISHED:
            torrent.files.progress = 100.0
        else:
            progress = self.Read("progress")
            if progress != "":
                try:
                    torrent.files.progress = float(progress)
                except:
                    pass
                
        # Local upload options
        localmax = self.Read("localmax", "int")
        if localmax != 0:
            torrent.connection.maxlocalrate['up'] = localmax

        localmaxdown = self.Read("localmaxdown", "int")
        if localmaxdown != 0:
            torrent.connection.maxlocalrate['down'] = localmaxdown

        maxupload = self.Read("maxupload", "int")
        torrent.connection.setMaxUpload(maxupload)

        for param in torrent.connection.seedoptions:
            value = self.Read(param)
            if value != "":
                torrent.connection.seedoptions[param] = value
                
        timeout = self.Read("timeout")
        if timeout == "0":
            torrent.connection.timeout = False
            
        seedtime = self.Read("seedtime")
        if seedtime != "":
            try:
                torrent.connection.seedingtime = int(seedtime)
                torrent.connection.seedingtimeleft -= torrent.connection.seedingtime
            except:
                pass

        if self.Exists("announces"):
            torrent.trackerlist = self.Read("announces", "bencode-list")
            torrent.updatetrackerlist()        
                
